home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / DEPCA.ASM < prev    next >
Assembly Source File  |  1991-01-27  |  19KB  |  828 lines

  1. version    equ    0
  2.  
  3.     include    defs.asm
  4.  
  5. NI_CSR        equ    0
  6. RBI        equ    2
  7. DATA_REG    equ    4
  8. ADDR_REG    equ    6
  9.     CSR0        equ    0
  10.     CSR1        equ    1
  11.     CSR2        equ    2
  12.     CSR3        equ    3
  13. EBASE        equ    0ch
  14.  
  15. outport    macro    reg
  16.     push    ax
  17.     setport    ADDR_REG
  18.     mov    ax,reg
  19.     out    dx,ax
  20.     in    ax,dx            ;always follow a write by a read
  21.  
  22.     setport    DATA_REG
  23.     pop    ax
  24.     out    dx,ax
  25.     in    ax,dx            ;always follow a write by a read
  26.  
  27.     endm
  28.  
  29.  
  30. ;
  31. ;     Control and Status Register 0 (CSR0) bit definitions
  32. ;
  33. CSR0_ERR    equ     8000h    ; Error summary
  34. CSR0_BABL    equ     4000h    ; Babble transmitter timeout error
  35. CSR0_CERR    equ    2000h    ; Collision Error
  36. CSR0_MISS    equ    1000h    ; Missed packet
  37. CSR0_MERR    equ    0800h    ; Memory Error
  38. CSR0_RINT    equ    0400h    ; Reciever Interrupt
  39. CSR0_TINT       equ    0200h    ; Transmit Interrupt
  40. CSR0_IDON    equ    0100h    ; Initialization Done
  41. CSR0_INTR    equ    0080h    ; Interrupt Flag
  42. CSR0_INEA    equ    0040h    ; Interrupt Enable
  43. CSR0_RXON    equ    0020h    ; Receiver on
  44. CSR0_TXON    equ    0010h   ; Transmitter on
  45. CSR0_TDMD    equ    0008h    ; Transmit Demand
  46. CSR0_STOP    equ    0004h     ; Stop
  47. CSR0_STRT    equ    0002h    ; Start
  48. CSR0_INIT    equ    0001h    ; Initialize
  49.  
  50. ;
  51. ;     Initialization Block  Mode operation Bit Definitions.
  52. ;
  53. M_PROM        equ    8000h    ; Promiscuous Mode
  54. M_INTL        equ    0040h   ; Internal Loopback
  55. M_DRTY        equ    0020h   ; Disable Retry
  56. M_COLL        equ    0010h    ; Force Collision
  57. M_DTCR        equ    0008h    ; Disable Transmit CRC)
  58. M_LOOP        equ    0004h    ; Loopback
  59. M_DTX        equ    0002h    ; Disable the Transmitter
  60. M_DRX        equ    0001h   ; Disable the Reciever
  61.  
  62.  
  63. ;
  64. ;     Receive message descriptor bit definitions.
  65. ;
  66. RCV_OWN        equ    8000h    ; owner bit 0 = host, 1 = lance
  67. RCV_ERR        equ    4000h    ; Error Summary
  68. RCV_FRAM    equ     2000h    ; Framing Error
  69. RCV_OFLO    equ    1000h    ; Overflow Error
  70. RCV_CRC        equ    0800h    ; CRC Error
  71. RCV_BUF_ERR    equ     0400h    ; Buffer Error
  72. RCV_START    equ    0200h    ; Start of Packet
  73. RCV_END        equ    0100h    ; End of Packet
  74.  
  75.  
  76. ;
  77. ;    Transmit  message descriptor bit definitions.
  78. ;
  79. XMIT_OWN    equ    8000h    ; owner bit 0 = host, 1 = lance
  80. XMIT_ERR    equ    4000h   ; Error Summary
  81. XMIT_RETRY    equ    1000h   ; more the 1 retry needed to Xmit
  82. XMIT_1_RETRY    equ    0800h    ; one retry needed to Xmit
  83. XMIT_DEF    equ    0400h    ; Deferred
  84. XMIT_START    equ    0200h    ; Start of Packet
  85. XMIT_END    equ    0100h    ; End of Packet
  86.  
  87. ;
  88. ;    Miscellaneous Equates
  89. ;
  90.  
  91. TRANSMIT_BUF_COUNT    equ    1
  92. RECEIVE_BUF_COUNT    equ    8
  93. TRANSMIT_BUF_SIZE    equ    1518
  94. RECEIVE_BUF_SIZE    equ    1518
  95.  
  96. ;
  97. ;    Receive Message Descriptor
  98. ;
  99. rcv_msg_dscp struc
  100.     rmd0    dw    ?    ; Rec. Buffer Lo-Address
  101.     rmd1    dw    ?    ; Status bits / Hi-Address
  102.     rmd2    dw    ?    ; Buff Byte-length (2's Comp)
  103.     rmd3    dw    ?    ; Receive message length
  104. rcv_msg_dscp ends
  105.  
  106.  
  107. ;
  108. ;    Transmit Message Descriptor
  109. ;
  110. xmit_msg_dscp struc
  111.     tmd0    dw    ?    ; Xmit Buffer Lo-Address
  112.     tmd1    dw    ?    ; Status bits / Hi-Address
  113.     tmd2     dw    ?    ; Buff Byte-length (2's Comp)
  114.     tmd3    dw    ?    ; Buffer Status bits & TDR value
  115. xmit_msg_dscp ends
  116.  
  117. lance_seg    segment at 0
  118.  
  119. ;
  120. ;the LANCE requires that the descriptor pointers be on a qword boundary.
  121. ;
  122.     align    8
  123.  
  124. transmit_dscps    xmit_msg_dscp    TRANSMIT_BUF_COUNT dup(<>)
  125. receive_dscps    rcv_msg_dscp    RECEIVE_BUF_COUNT dup(<>)
  126.  
  127. ;
  128. ;      LANCE Initialization Block
  129. ;
  130.     align    2
  131. init_block        label    byte
  132. init_mode        dw    0
  133. init_addr        db    EADDR_LEN dup(?)    ; Our Ethernet address
  134. init_filter        db    8 dup(0)    ;Multicast filter.
  135. init_receive        dw    ?,?        ;Receive Ring Pointer.
  136. init_transmit          dw    ?,?          ;Transmit Ring Pointer.
  137.  
  138. transmit_bufs    equ    $
  139. receive_bufs    equ    transmit_bufs + TRANSMIT_BUF_COUNT * TRANSMIT_BUF_SIZE
  140.  
  141. lance_seg    ends
  142.  
  143. code    segment    para public
  144.     assume    cs:code, ds:code
  145.  
  146.         public    int_no
  147. int_no        db    2,0,0,0            ;must be four bytes long for get_number.
  148. io_addr        dw    -1,-1
  149. base_addr    dw    -1,-1
  150. depca_pattern    db    0FFh, 00h, 55h, 0AAh, 0FFh, 00h, 55h, 0AAh
  151.  
  152.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  153. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  154. driver_type    db    66        ;from the packet spec
  155. driver_name    db    'DEPCA',0    ;name of the driver.
  156. driver_function    db    2        ;basic, extended
  157. parameter_list    label    byte
  158.     db    1    ;major rev of packet driver
  159.     db    9    ;minor rev of packet driver
  160.     db    14    ;length of parameter list
  161.     db    EADDR_LEN    ;length of MAC-layer address
  162.     dw    GIANT    ;MTU, including MAC headers
  163.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  164.     dw    RECEIVE_BUF_COUNT-1    ;(# of back-to-back MTU rcvs) - 1
  165.     dw    TRANSMIT_BUF_COUNT-1    ;(# of successive xmits) - 1
  166. int_num    dw    0    ;Interrupt # to hook for post-EOI
  167.             ;processing, 0 == none,
  168.  
  169.     public    rcv_modes
  170. rcv_modes    dw    7        ;number of receive modes in our table.
  171.         dw    0               ;There is no mode zero
  172.         dw    rcv_mode_1
  173.         dw    0        ;only ours.
  174.         dw    rcv_mode_3    ;ours plus broadcast
  175.         dw    0        ;some multicasts
  176.         dw    rcv_mode_5    ;all multicasts
  177.         dw    rcv_mode_6    ;all packets
  178.  
  179. transmit_head    dw    transmit_dscps    ;->next packet to be filled by host.
  180. receive_head    dw    receive_dscps    ;->next packet to be filled by LANCE.
  181.  
  182.     public    as_send_pkt
  183. ; The Asynchronous Transmit Packet routine.
  184. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  185. ;   interrupts possibly enabled.
  186. ; Exit with nc if ok, or else cy if error, dh set to error number.
  187. ;   es:di and interrupt enable flag preserved on exit.
  188. as_send_pkt:
  189.     ret
  190.  
  191.     public    drop_pkt
  192. ; Drop a packet from the queue.
  193. ; Enter with es:di -> iocb.
  194. drop_pkt:
  195.     assume    ds:nothing
  196.     ret
  197.  
  198.     public    xmit
  199. ; Process a transmit interrupt with the least possible latency to achieve
  200. ;   back-to-back packet transmissions.
  201. ; May only use ax and dx.
  202. xmit:
  203.     assume    ds:nothing
  204.     ret
  205.  
  206.  
  207.     public    send_pkt
  208. send_pkt:
  209. ;enter with ds:si -> packet, cx = packet length.
  210. ;exit with nc if ok, or else cy if error, dh set to error number.
  211.     assume    ds:nothing
  212.     mov    es,base_addr
  213.     assume    es:lance_seg
  214.  
  215.     xor    bx,bx
  216.  
  217.     mov    ax,18
  218.     call    set_timeout
  219. send_pkt_1:
  220.     test    transmit_dscps[bx].tmd1,XMIT_OWN    ;Did the lance chip give it back?
  221.     je    send_pkt_2
  222.     call    do_timeout
  223.     jne    send_pkt_1
  224.     mov    dh,CANT_SEND
  225.     stc
  226.     ret
  227. send_pkt_2:
  228. ;reset error indications.
  229.     and    transmit_dscps[bx].tmd1,not (XMIT_ERR or XMIT_DEF or XMIT_1_RETRY or XMIT_RETRY)    ;Did the lance chip give it back?
  230.     mov    transmit_dscps[bx].tmd3,0    ;reset all error bits.
  231.  
  232.     mov    ax,cx            ;store the count.
  233.     cmp    ax,RUNT            ; minimum length for Ether
  234.     ja    oklen
  235.     mov    ax,RUNT            ; make sure size at least RUNT
  236. oklen:
  237.     neg    ax
  238.     mov    transmit_dscps[bx].tmd2,ax    ;store the negative of the cnt.
  239.  
  240.     mov    ax,transmit_dscps[bx].tmd0    ;store the packet.
  241.     mov    dx,transmit_dscps[bx].tmd1
  242.     call    phys_to_segmoffs
  243.     assume    es:nothing
  244.     rep    movsb
  245.  
  246.     mov    es,base_addr
  247.     assume    es:lance_seg
  248.     or    transmit_dscps[bx].tmd1,XMIT_OWN    ;give it to the lance chip.
  249.  
  250. ;Inform LANCE that it should poll for a packet.
  251.     loadport
  252.     mov    ax,CSR0_INEA or CSR0_TDMD
  253.     outport    CSR0
  254.     clc
  255.     ret
  256.  
  257.  
  258. detect_board:
  259. ;test to see if a board is located at io_addr.
  260. ;setup to read first byte of ethernet address rom when successful.
  261. ;return nz if not.
  262.     assume    cs:code, ds:code
  263.  
  264.     loadport
  265.     setport    EBASE
  266.     mov    si, offset depca_pattern
  267.     lodsb                ;get first char of test pattern
  268.     mov    ah,al            ;move string byte to ah
  269.     mov    di,0
  270.     mov    cx,32            ;do 32 reps
  271. detect_board_1:
  272.     in    al,dx            ;input byte
  273.     cmp    ah,al
  274.     jne    detect_board_2
  275.     lodsb                ;get next char
  276.     mov    ah,al
  277.     inc    di
  278.     cmp    di, 8            ;need to match eight chars
  279.     je    detect_board_done
  280. detect_board_2:
  281.     loop    detect_board_1
  282.     or    sp,sp            ;guaranteed to be nonzero.
  283. detect_board_done:
  284.     ret
  285.  
  286.  
  287.     public    get_address
  288. get_address:
  289. ;get the address of the interface.
  290. ;enter with es:di -> place to get the address, cx = size of address buffer.
  291. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  292.     assume    ds:code, es:nothing
  293.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  294.     jb    get_address_2
  295.     push    di
  296.     call    detect_board
  297.     pop    di
  298.     mov    cx,EADDR_LEN
  299.     loadport            ; Get our Ethernet address base.
  300.     setport    EBASE+1
  301.     cld
  302. get_address_1:
  303.     in    al,dx            ; get a byte of the eprom address
  304.     stosb
  305.     loop    get_address_1        ; go back for rest
  306.     mov    cx,EADDR_LEN
  307.     clc
  308.     ret
  309. get_address_2:
  310.     stc
  311.     ret
  312.  
  313.  
  314.     public    set_address
  315. set_address:
  316. ;enter with ds:si -> Ethernet address, CX = length of address.
  317. ;exit with nc if okay, or cy, dh=error if any errors.
  318.     assume    ds:nothing
  319.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  320.     je    set_address_4
  321.     mov    dh,BAD_ADDRESS
  322.     stc
  323.     jmp    short set_address_done
  324. set_address_4:
  325.  
  326.     mov    es,base_addr
  327.     mov    di,offset init_addr
  328.     rep    movsb
  329.     call    initialize        ;initialize with our new address.
  330.  
  331. set_address_okay:
  332.     mov    cx,EADDR_LEN        ;return their address length.
  333.     clc
  334. set_address_done:
  335.     push    cs
  336.     pop    ds
  337.     assume    ds:code
  338.     ret
  339.  
  340.  
  341. rcv_mode_1:
  342.     mov    ax,M_DRX or M_DTX    ;disable the receiver and transmitter.
  343.     jmp    initialize_nomulti
  344. rcv_mode_3:
  345.     xor    ax,ax            ;don't accept any multicast frames.
  346.     call    initialize_multi
  347.     mov    ax,0            ;non-promiscuous mode
  348.     jmp    short initialize_nomulti
  349. rcv_mode_5:
  350.     mov    ax,-1            ;accept any multicast frames.
  351.     call    initialize_multi
  352.     mov    ax,0            ;non-promiscuous mode
  353.     jmp    short initialize_nomulti
  354. rcv_mode_6:
  355.     mov    ax,M_PROM    ;promiscuous mode
  356. initialize_nomulti:
  357. initialize:
  358.     mov    es,base_addr
  359.     mov    es:init_mode,ax
  360.  
  361.     loadport
  362.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  363.     outport    CSR0
  364.  
  365.     mov    ax,CSR0_INEA or CSR0_STRT or CSR0_INIT    ;reinit and restart.
  366.     outport    CSR0
  367.  
  368.     setport    DATA_REG
  369.  
  370.     mov    ax,36            ;wait one second for the board
  371.     call    set_timeout        ;  to timeout.
  372. initialize_1:
  373.     in    ax,dx
  374.     test    ax,CSR0_IDON
  375.     jne    initialize_2
  376.     call    do_timeout
  377.     jne    initialize_1
  378.     stc
  379.     ret
  380. initialize_2:
  381.     clc
  382.     ret
  383.  
  384.  
  385. initialize_multi:
  386. ;enter with ax = value for all multicast hash bits.
  387.     mov    es,base_addr
  388.     mov    di,offset init_filter
  389.     mov    cx,8/2
  390.     rep    stosw
  391.     ret
  392.  
  393.  
  394.     public    set_multicast_list
  395. set_multicast_list:
  396. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  397. ;return nc if we set all of them, or cy,dh=error if we didn't.
  398.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  399.     stc
  400.     ret
  401.  
  402.  
  403.     public    terminate
  404. terminate:
  405.     call    rcv_mode_1        ;don't receive any apckets.
  406.  
  407.     ret
  408.  
  409.     public    reset_interface
  410. reset_interface:
  411. ;reset the interface.
  412.     assume    ds:code
  413.     ret
  414.  
  415.  
  416. ;called when we want to determine what to do with a received packet.
  417. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  418.     extrn    recv_find: near
  419.  
  420. ;called after we have copied the packet into the buffer.
  421. ;enter with ds:si ->the packet, cx = length of the packet.
  422.     extrn    recv_copy: near
  423.  
  424.     extrn    count_in_err: near
  425.     extrn    count_out_err: near
  426.  
  427. LANCE_ISR_ACKNOWLEDGE equ (CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  428.  
  429.     public    recv
  430. recv:
  431. ;called from the recv isr.  All registers have been saved, and ds=cs.
  432. ;Upon exit, the interrupt will be acknowledged.
  433.     assume    ds:code
  434.  
  435.     loadport
  436.     setport    ADDR_REG
  437.     mov    ax,CSR0
  438.     out    dx,ax
  439.     in    ax,dx
  440.     setport    DATA_REG
  441.     in    ax,dx
  442.     mov    bx,ax            ;make a copy.
  443.  
  444. ; Acknowledge the Interrupt from the controller, but disable further
  445. ; controller Interrupts until we service the current interrupt.
  446. ;
  447. ;(CSR0_INEA or CSR0_TDMD or CSR0_STOP or CSR0_STRT or CSR0_INIT)
  448. ;
  449.     and    ax,not LANCE_ISR_ACKNOWLEDGE
  450.     out    dx,ax
  451.     in    ax,dx        ; follow all writes by a read
  452.  
  453.     test    bx,CSR0_RINT        ;receive interrupt?
  454.     jne    recv_RINT        ;yes.
  455.     jmp    recv_done        ;no, we're done.
  456. recv_RINT:
  457.  
  458.     mov    es,base_addr
  459.     assume    es:lance_seg
  460.     mov    bx,receive_head
  461.  
  462. recv_search:
  463.     test    lance_seg:[bx].rmd1,RCV_OWN    ;do we own this buffer?
  464.     je    recv_own        ;yes - process it.
  465.     call    inc_recv_ring        ;go to the next one.
  466.     cmp    bx,receive_head        ;did we get back to the beginning?
  467.     jne    recv_search        ;not yet.
  468.     jmp    recv_done        ;yes -- spurious interrupt!
  469. recv_own:
  470.     test    lance_seg:[bx].rmd1,RCV_ERR    ;Any errors in this buffer?
  471.     jne    recv_err        ;yes -- ignore this packet.
  472.  
  473.     mov    cx,lance_seg:[bx].rmd3
  474.     and    cx,0fffh        ;strip off the reserved bits
  475.  
  476.     mov    ax,lance_seg:[bx].rmd0    ;fetch the packet.
  477.     mov    dx,lance_seg:[bx].rmd1
  478.     call    phys_to_segmoffs
  479.     assume    es:nothing
  480.  
  481.     push    es
  482.     push    di
  483.     push    bx
  484.  
  485.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  486.                     ;  point to the packet type.
  487.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  488.     mov    ax, es:[di]
  489.     xchg    ah, al
  490.     cmp     ax, 1500
  491.     ja    BlueBookPacket
  492.     inc    di            ;set di to 802.2 header
  493.     inc    di
  494.     mov    dl, IEEE8023
  495. BlueBookPacket:
  496.     push    cx
  497.     call    recv_find
  498.     pop    cx
  499.  
  500.     pop    bx
  501.     pop    si
  502.     pop    ds
  503.     assume    ds:nothing, es:nothing
  504.  
  505.     mov    ax,es            ;is this pointer null?
  506.     or    ax,di
  507.     je    recv_free        ;yes - just free the frame.
  508.  
  509.     push    es
  510.     push    di
  511.     push    cx
  512.     rep    movsb
  513.     pop    cx
  514.     pop    si
  515.     pop    ds
  516.     assume    ds:nothing
  517.  
  518.     call    recv_copy
  519.  
  520.     jmp    short recv_free
  521.  
  522. recv_err:
  523.     call    count_in_err
  524. recv_free:
  525.     push    cs
  526.     pop    ds
  527.     assume    ds:code
  528.     mov    es,base_addr
  529.     assume    es:lance_seg
  530.  
  531. ;clear any error bits.
  532.     and    lance_seg:[bx].rmd1,not (RCV_ERR or RCV_FRAM or RCV_OFLO or RCV_CRC or RCV_BUF_ERR)
  533.     or    lance_seg:[bx].rmd1,RCV_OWN    ;give it back to the lance.
  534.     call    inc_recv_ring            ;go to the next one.
  535.     test    lance_seg:[bx].rmd1,RCV_OWN    ;Do we own this one?
  536.     je    recv_own
  537.     mov    receive_head,bx        ;remember where the next one starts.
  538. recv_done:
  539.     loadport            ;enable interrupts again.
  540.     setport    DATA_REG
  541.     mov    ax,CSR0_INEA
  542.     out    dx,ax
  543.  
  544.     ret
  545.  
  546.  
  547. inc_recv_ring:
  548. ;advance bx to the next receive ring descriptor.
  549.     assume    ds:nothing
  550.     add    bx,(size rcv_msg_dscp)
  551.     cmp    bx,offset receive_dscps + RECEIVE_BUF_COUNT * (size rcv_msg_dscp)
  552.     jb    inc_recv_ring_1
  553.     mov    bx,offset receive_dscps
  554. inc_recv_ring_1:
  555.     ret
  556.  
  557.  
  558.     public    recv_exiting
  559. recv_exiting:
  560. ;called from the recv isr after interrupts have been acknowledged.
  561. ;Only ds and ax have been saved.
  562.     assume    ds:nothing
  563.     ret
  564.  
  565.  
  566. phys_to_segmoffs:
  567. ;enter with dx:ax as the physical address of the buffer,
  568. ;exit with es:di -> buffer.
  569.     assume    ds:nothing
  570.   if 0
  571.     shl    dx,16-4            ;move the upper four bits into position.
  572.     mov    di,ax            ;now get the low 12 bits of the segment.
  573.     shr    di,4
  574.     or    dx,di            ;combine them.
  575.     mov    es,dx
  576.     mov    di,ax
  577.     and    di,0fh            ;now compute the offset.
  578.   else
  579.     mov    es,base_addr
  580.     mov    di,ax
  581.   endif
  582.     ret
  583.  
  584.     include    timeout.asm
  585.  
  586. end_resident    label    byte
  587.  
  588.     public    usage_msg
  589. usage_msg    db    "usage: depca [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr> <mem_addr>",CR,LF,'$'
  590. no_board_msg    db    "No DEPCA detected.",CR,LF,'$'
  591. io_addr_funny_msg    label    byte
  592.         db    "No DEPCA detected, continuing anyway.",CR,LF,'$'
  593. bad_reset_msg    db    "Unable to reset the DEPCA.",CR,LF,'$'
  594. bad_init_msg    db    "Unable to initialize the DEPCA.",CR,LF,'$'
  595.  
  596.     public    copyright_msg
  597. copyright_msg    db    "Packet driver for a Digital Equipment Corporation DEPCA, version ",'0'+majver,".",'0'+version,CR,LF
  598.         db    '$'
  599.  
  600. int_no_name    db    "Interrupt number ",'$'
  601. io_addr_name    db    "I/O port ",'$'
  602. base_addr_name    db    "Memory address ",'$'
  603.  
  604.     extrn    set_recv_isr: near
  605.     extrn    maskint: near
  606.  
  607. ;enter with si -> argument string, di -> dword to store.
  608. ;if there is no number, don't change the number.
  609.     extrn    get_number: near
  610.  
  611. ;enter with si -> argument string, di -> dword to print.
  612.     extrn    print_number: near
  613.  
  614.     public    parse_args
  615. parse_args:
  616. ;exit with nc if all went well, cy otherwise.
  617.     assume    ds:code
  618.     mov    di,offset int_no
  619.     call    get_number
  620.     mov    di,offset io_addr
  621.     call    get_number
  622.     mov    di,offset base_addr
  623.     call    get_number
  624.     clc
  625.     ret
  626.  
  627.  
  628.     public    etopen
  629. etopen:
  630.     assume    ds:code
  631.  
  632.     cmp    io_addr,-1        ;Did they ask for auto-detect?
  633.     je    find_board
  634.  
  635.     call    detect_board        ;no, just verify its existance.
  636.     je    find_board_found
  637.  
  638.     mov    dx,offset io_addr_funny_msg
  639.     mov    ah,9
  640.     int    21h
  641.  
  642.     jmp    find_board_found
  643.  
  644. find_board:
  645.     mov    io_addr,300h        ;Search for the Ethernet address at 300h
  646.     mov    io_addr+2,0
  647.     call    detect_board
  648.     je    find_board_found
  649.     mov    io_addr,200h        ;Search at 200h
  650.     call    detect_board
  651.     je    find_board_found
  652.  
  653.     mov    dx,offset no_board_msg    ;Tell them that we can't find it.
  654.     mov    ah,9
  655.     int    21h
  656.  
  657.     stc
  658.     ret
  659. find_board_found:
  660.  
  661.     mov    al, int_no        ; Get board's interrupt vector
  662.     add    al, 8
  663.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  664.     jb    set_int_num        ; No.
  665.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  666. set_int_num:
  667.     xor    ah, ah            ; Clear high byte
  668.     mov    int_num, ax        ; Set parameter_list int num.
  669.  
  670.     mov    al,int_no
  671.     call    maskint            ;disable these interrupts.
  672.  
  673.     loadport
  674.     mov    ax,CSR0_STOP        ;reset the INIT bit.
  675.     outport    CSR0
  676.  
  677. ;set up transmit descriptor ring.
  678.     mov    es,base_addr
  679.     assume    es:lance_seg
  680.     mov    cx,TRANSMIT_BUF_COUNT
  681.     mov    bx,offset transmit_dscps
  682.     mov    di,offset transmit_bufs
  683. setup_transmit:
  684.     call    segmoffs_to_phys
  685.  
  686.     or    dx,XMIT_START or XMIT_END
  687.     mov    lance_seg:[bx].tmd0,ax        ;points to the buffer.
  688.     mov    lance_seg:[bx].tmd1,dx
  689.  
  690.     add    bx,(size xmit_msg_dscp)
  691.     add    di,TRANSMIT_BUF_SIZE
  692.     loop    setup_transmit
  693.  
  694. ;set up receive descriptor ring.
  695.     mov    cx,RECEIVE_BUF_COUNT
  696.     mov    bx,offset receive_dscps
  697.     mov    di,offset receive_bufs
  698. setup_receive:
  699.     call    segmoffs_to_phys
  700.  
  701.     or    dx,RCV_OWN
  702.     mov    lance_seg:[bx].rmd0,ax        ;points to the buffer.
  703.     mov    lance_seg:[bx].rmd1,dx
  704.  
  705.     mov    lance_seg:[bx].rmd2,-RECEIVE_BUF_SIZE
  706.     mov    lance_seg:[bx].rmd3,0
  707.  
  708.     add    bx,(size rcv_msg_dscp)
  709.     add    di,RECEIVE_BUF_SIZE
  710.     loop    setup_receive
  711.  
  712. ;initialize the board.
  713.     mov    cx,EADDR_LEN        ;get our address.
  714.     mov    di,offset init_addr
  715.     call    get_address
  716.  
  717.     mov    cx,RECEIVE_BUF_COUNT
  718.     call    compute_log2
  719.  
  720.     mov    di,offset receive_dscps
  721.     call    segmoffs_to_phys
  722.     or    dx,cx            ;include the buffer size bits.
  723.     mov    init_receive[0],ax
  724.     mov    init_receive[2],dx
  725.  
  726.     mov    cx,TRANSMIT_BUF_COUNT
  727.     call    compute_log2
  728.  
  729.     mov    di,offset transmit_dscps
  730.     call    segmoffs_to_phys
  731.     or    dx,cx            ;include the buffer size bits.
  732.     mov    init_transmit[0],ax
  733.     mov    init_transmit[2],dx
  734.  
  735.     mov    di,offset init_block    ;now tell the board where the init
  736.     call    segmoffs_to_phys    ;  block is.
  737.  
  738.     push    dx
  739.     push    ax
  740.  
  741.     loadport
  742.     mov    ax,2            ;write the bus config register.
  743.     outport    CSR3
  744.  
  745.     pop    ax            ;write the low word.
  746.     outport    CSR1
  747.  
  748.     pop    ax            ;write the high word.
  749.     outport    CSR2
  750.  
  751.     xor    ax,ax            ;don't accept any multicast frames.
  752.     call    initialize_multi
  753.     mov    ax,0            ;non-promiscuous mode
  754.     call    initialize
  755.     jnc    init_ok
  756.  
  757.     mov    dx,offset bad_init_msg
  758.     mov    ah,9
  759.     int    21h
  760.  
  761.     stc
  762.     ret
  763.  
  764. init_ok:
  765. ;
  766. ; Now hook in our interrupt
  767. ;
  768.     call    set_recv_isr
  769.  
  770.     loadport
  771.     setport    NI_CSR
  772.     mov    al,82h            ;disable ROM, enable the interrupt line
  773.     out    dx,al
  774.  
  775.     mov    dx,offset end_resident
  776.     clc
  777.     ret
  778.  
  779.     public    print_parameters
  780. print_parameters:
  781. ;echo our command-line parameters
  782.     mov    di,offset int_no
  783.     mov    dx,offset int_no_name
  784.     call    print_number
  785.     mov    di,offset io_addr
  786.     mov    dx,offset io_addr_name
  787.     call    print_number
  788.     mov    di,offset base_addr
  789.     mov    dx,offset base_addr_name
  790.     call    print_number
  791.     ret
  792.  
  793. compute_log2:
  794. ;enter with cx = number of buffers.
  795. ;exit with cx = log2(number of buffers) << 13.
  796.     mov    ax,-1
  797. compute_log2_1:
  798.     inc    ax
  799.     shr    cx,1
  800.     jne    compute_log2_1
  801.     mov    cl,13
  802.     shl    ax,cl
  803.     mov    cx,ax
  804.     ret
  805.  
  806.  
  807. segmoffs_to_phys:
  808. ;enter with es:di -> buffer.
  809. ;exit with dx:ax as the physical address of the buffer,
  810.  
  811.   if 0    ; The DEPCA doesn't use system memory, it uses its own.
  812.     mov    dx,es            ;get the high 4 bits of the segment,
  813.     shr    dx,16-4
  814.     mov    ax,es            ;and the low 12 bits of the segment.
  815.     shl    ax,4
  816.     add    ax,di            ;add in the offset.
  817.     adc    dx,0
  818.   else
  819.     xor    dx,dx            ;the offset is the only part of the
  820.     mov    ax,di            ;  address.
  821.   endif
  822.     ret
  823.  
  824.  
  825. code    ends
  826.  
  827.     end
  828.